﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.Globalization;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Media.Imaging;
using System.Reflection;

using C1.Phone.Pdf;
using System.Threading;
using System.ComponentModel;


namespace ControlExplorer.Controls.Pdf
{
    public static class PdfCodeSamples
    {
        //---------------------------------------------------------------------------------
        #region ** images

        public static void CreateDocumentImages(C1PdfDocument pdf)
        {
            // calculate page rect (discounting margins)
            Rect rcPage = PdfUtils.PageRectangle(pdf);

            // load image into writeable bitmap

            var bi = new BitmapImage();
            bi.CreateOptions = BitmapCreateOptions.None;
            bi.UriSource = new Uri("/ControlExplorer" + App.AssemblySuffix + ";component/Resources/Pics/pic1.jpg", UriKind.Relative);
            var wb = new WriteableBitmap(bi);            

            // center image on page preserving aspect ratio
            pdf.DrawImage(wb, rcPage, ContentAlignment.MiddleCenter, Stretch.Uniform);
        }

        #endregion

        //---------------------------------------------------------------------------------
        #region ** paper sizes

        public static void CreateDocumentPaperSizes(C1PdfDocument pdf)
        {
            // add title
            Font titleFont = new Font("Tahoma", 24, PdfFontStyle.Bold);
            Rect rc = PdfUtils.PageRectangle(pdf);
            PdfUtils.RenderParagraph(pdf, pdf.DocumentInfo.Title, titleFont, rc, rc, false);

            // create constant font and StringFormat objects
            Font font = new Font("Tahoma", 18);
            StringFormat sf = new StringFormat();
            sf.Alignment = HorizontalAlignment.Center;
            sf.LineAlignment = VerticalAlignment.Center;

            // create one page with each paper size
            bool firstPage = true;
            foreach (var fi in typeof(PaperKind).GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                // Silverlight doesn't have Enum.GetValues
                PaperKind pk = (PaperKind)fi.GetValue(null);

                // skip custom size
                if (pk == PaperKind.Custom) continue;

                // add new page for every page after the first one
                if (!firstPage) pdf.NewPage();
                firstPage = false;

                // set paper kind and orientation
                pdf.PaperKind = pk;
                pdf.Landscape = !pdf.Landscape;

                // draw some content on the page
                rc = PdfUtils.PageRectangle(pdf);
                rc = PdfUtils.Inflate(rc, -6, -6);
                string text = string.Format("PaperKind: [{0}];\r\nLandscape: [{1}];\r\nFont: [Tahoma 18pt]",
                    pdf.PaperKind, pdf.Landscape);
                pdf.DrawString(text, font, Colors.Black, rc, sf);
                pdf.DrawRectangle(Colors.Black, rc);
            }
        }

        #endregion

        //---------------------------------------------------------------------------------
        #region ** table of contents

        public static void CreateDocumentTOC(C1PdfDocument pdf)
        {
            // create pdf document
            pdf.DocumentInfo.Title = "Table of Contents";

            // add title
            Font titleFont = new Font("Tahoma", 24, PdfFontStyle.Bold);
            Rect rcPage = PdfUtils.PageRectangle(pdf);
            Rect rc = PdfUtils.RenderParagraph(pdf, pdf.DocumentInfo.Title, titleFont, rcPage, rcPage, false);
            rc.Y += 12;

            // create nonsense document
            var bkmk = new List<string[]>();
            Font headerFont = new Font("Arial", 14, PdfFontStyle.Bold);
            Font bodyFont = new Font("Times New Roman", 11);
            for (int i = 0; i < 30; i++)
            {
                // create ith header (as a link target and outline entry)
                string header = string.Format("{0}. {1}", i + 1, BuildRandomTitle());
                rc = PdfUtils.RenderParagraph(pdf, header, headerFont, rcPage, rc, true, true);

                // save bookmark to build TOC later
                int pageNumber = pdf.CurrentPage + 1;
                bkmk.Add(new string[] { pageNumber.ToString(), header });

                // create some text
                rc.X += 36;
                rc.Width -= 36;
                for (int j = 0; j < 3 + _rnd.Next(20); j++)
                {
                    string text = BuildRandomParagraph();
                    rc = PdfUtils.RenderParagraph(pdf, text, bodyFont, rcPage, rc);
                    rc.Y += 6;
                }
                rc.X -= 36;
                rc.Width += 36;
                rc.Y += 20;
            }

            // start Table of Contents
            pdf.NewPage();					// start TOC on a new page
            int tocPage = pdf.CurrentPage;	// save page index (to move TOC later)
            rc = PdfUtils.RenderParagraph(pdf, "Table of Contents", titleFont, rcPage, rcPage, true);
            rc.Y += 12;
            rc.X += 30;
            rc.Width -= 40;

            // render Table of Contents
            Pen dottedPen = new Pen(Colors.Gray, 1.5f);
            dottedPen.DashStyle = DashStyle.Dot;
            StringFormat sfRight = new StringFormat();
            sfRight.Alignment = HorizontalAlignment.Right;
            rc.Height = bodyFont.Size * 1.2;
            foreach (string[] entry in bkmk)
            {
                // get bookmark info
                string page = entry[0];
                string header = entry[1];

                // render header name and page number
                pdf.DrawString(header, bodyFont, Colors.Black, rc);
                pdf.DrawString(page, bodyFont, Colors.Black, rc, sfRight);

#if true
                // connect the two with some dots (looks better than a dotted line)
                string dots = ". ";
                var wid = pdf.MeasureString(dots, bodyFont).Width;
                var x1 = rc.X + pdf.MeasureString(header, bodyFont).Width + 8;
                var x2 = rc.Right - pdf.MeasureString(page, bodyFont).Width - 8;
                var x = rc.X;
                for (rc.X = x1; rc.X < x2; rc.X += wid)
                {
                    pdf.DrawString(dots, bodyFont, Colors.Gray, rc);
                }
                rc.X = x;
#else 
				// connect with a dotted line (another option)
				var x1 = rc.X + pdf.MeasureString(header, bodyFont).Width + 5;
				var x2 = rc.Right - pdf.MeasureString(page, bodyFont).Width  - 5;
				var y  = rc.Top + bodyFont.Size;
				pdf.DrawLine(dottedPen, x1, y, x2, y);
#endif
                // add local hyperlink to entry
                pdf.AddLink("#" + header, rc);

                // move on to next entry
                rc = PdfUtils.Offset(rc, 0, rc.Height);
                if (rc.Bottom > rcPage.Bottom)
                {
                    pdf.NewPage();
                    rc.Y = rcPage.Y;
                }
            }

            // move table of contents to start of document
            PdfPage[] arr = new PdfPage[pdf.Pages.Count - tocPage];
            pdf.Pages.CopyTo(tocPage, arr, 0, arr.Length);
            pdf.Pages.RemoveRange(tocPage, arr.Length);
            pdf.Pages.InsertRange(0, arr);
        }

        static string BuildRandomTitle()
        {
            string[] a1 = "Learning|Explaining|Mastering|Forgetting|Examining|Understanding|Applying|Using|Destroying".Split('|');
            string[] a2 = "Music|Tennis|Golf|Zen|Diving|Modern Art|Gardening|Architecture|Mathematics|Investments|.NET|Java".Split('|');
            string[] a3 = "Quickly|Painlessly|The Hard Way|Slowly|Painfully|With Panache".Split('|');
            return string.Format("{0} {1} {2}", a1[_rnd.Next(a1.Length - 1)], a2[_rnd.Next(a2.Length - 1)], a3[_rnd.Next(a3.Length - 1)]);
        }

        static string BuildRandomParagraph()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 5 + _rnd.Next(10); i++)
            {
                sb.AppendFormat(BuildRandomSentence());
            }
            return sb.ToString();
        }
        static string BuildRandomSentence()
        {
            string[] a1 = "Artists|Movie stars|Musicians|Politicians|Computer programmers|Modern thinkers|Gardeners|Experts|Some people|Hockey players".Split('|');
            string[] a2 = "know|seem to think about|care about|often discuss|dream about|hate|love|despise|respect|long for|pay attention to|embrace".Split('|');
            string[] a3 = "the movies|chicken soup|tea|many things|sushi|my car|deep thoughs|tasteless jokes|vaporware|cell phones|hot dogs|ballgames".Split('|');
            string[] a4 = "incessantly|too much|easily|without reason|rapidly|sadly|randomly|vigorously|more than usual|with enthusiasm|shamelessly|on Tuesdays".Split('|');
            return string.Format("{0} {1} {2} {3}. ", a1[_rnd.Next(a1.Length - 1)], a2[_rnd.Next(a2.Length - 1)], a3[_rnd.Next(a3.Length - 1)], a4[_rnd.Next(a4.Length - 1)]);
        }
        static Random _rnd = new Random();

        #endregion

        //---------------------------------------------------------------------------------
        #region ** text

        public static void CreateDocumentText(C1PdfDocument pdf)
        {
            // use landscape for more impact
            pdf.Landscape = true;

            // measure and show some text 
            var text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
            var font = new Font("Times New Roman", 9, PdfFontStyle.Italic);

            // create StringFormat used to set text alignment and line spacing
            var fmt = new StringFormat();
            fmt.LineSpacing = -1.5; // 1.5 char height
            fmt.Alignment = HorizontalAlignment.Center;

            // measure it
            var sz = pdf.MeasureString(text, font, 72 * 3, fmt);
            var rc = new Rect(pdf.PageRectangle.Width / 2, 72, sz.Width, sz.Height);
            rc = PdfUtils.Offset(rc, 72, 0);

            // draw a rounded frame
            rc = PdfUtils.Inflate(rc, 10, 10);
            pdf.FillRectangle(Colors.Black, rc, new Size(30, 30));
            pdf.DrawRectangle(new Pen(Colors.Red, 4), rc, new Size(30, 30));
            rc = PdfUtils.Inflate(rc, -10, -10);

            // draw the text
            pdf.DrawString(text, font, Colors.White, rc, fmt);

            // now draw some text rotating about the center of the page
            rc = pdf.PageRectangle;
            rc = PdfUtils.Offset(rc, rc.Width / 2, rc.Height / 2);

            // build StringFormat used to rotate the text
            fmt = new StringFormat();

            // rotate the string in small increments
            var step = 6;
            text = "PDF works in Silverlight!";
            for (int i = 0; i <= 360; i += step)
            {
                fmt.Angle = i;
                font = new Font("Courier New", 8 + i / 30.0, PdfFontStyle.Bold);
                byte b = (byte)(255 * (1 - i / 360.0));
                pdf.DrawString(text, font, Color.FromArgb(0xff, b, b, b), rc, fmt);
            }
        }

        #endregion

        //---------------------------------------------------------------------------------
        #region ** graphics

        public static void CreateDocumentGraphics(C1PdfDocument pdf)
        {
            // set up to draw
            Rect rc = new Rect(0, 0, 300, 200);
            string text = "Hello world of .NET Graphics and PDF.\r\nNice to meet you.";
            Font font = new Font("Times New Roman", 12, PdfFontStyle.Italic | PdfFontStyle.Underline);

            // draw to pdf document
            int penWidth = 0;
            byte penRGB = 0;
            pdf.FillPie(Colors.Red, rc, 0, 20f);
            pdf.FillPie(Colors.Green, rc, 20f, 30f);
            pdf.FillPie(Colors.Blue, rc, 60f, 12f);
            pdf.FillPie(Colors.Orange, rc, -80f, -20f);
            for (float startAngle = 0; startAngle < 360; startAngle += 40)
            {
                Color penColor = Color.FromArgb(0xff, penRGB, penRGB, penRGB);
                Pen pen = new Pen(penColor, penWidth++);
                penRGB = (byte)(penRGB + 20);
                pdf.DrawArc(pen, rc, startAngle, 40f);
            }
            pdf.DrawRectangle(Colors.Red, rc);
            pdf.DrawString(text, font, Colors.Black, rc);

            // show a Bezier curve
            var pts = new Point[]
			{
				new Point(400, 100), new Point(420,  30),
				new Point(500, 140), new Point(530,  20),
			};

            // draw Bezier 
            pdf.DrawBezier(new Pen(Colors.Blue, 4), pts[0], pts[1], pts[2], pts[3]);

            // show Bezier control points
            pdf.DrawLines(Colors.Gray, pts);
            foreach (Point pt in pts)
            {
                pdf.FillRectangle(Colors.Red, pt.X - 2, pt.Y - 2, 4, 4);
            }

            // title
            pdf.DrawString("Simple Bezier", font, Colors.Black, new Rect(500, 150, 100, 100));
        }

        #endregion

    }
}
